package org.raymond.iworks.study.netty.official.fundamental.time;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

/**
 * @author raymond
 * @version V1.0
 * @Description: 第一个解决方案
 * (1) ChannelHandler有两个和生命周期相关的callback: handlerAdded()和handlerRemoved().
 * 你可以在这两个方法中执行任何初始化或反初始化方法,但是不能长时间阻塞该方法.
 * (2) 首先,所有收到的数据都会累积到buf中
 * (3) 然后,handler必须检查buf中是否有足够的数据可供处理,本例中是4字节,进行相关的逻辑处理.
 * 如果不够4个字节,Netty将继续调用channelRead()方法来接收更多的数据
 *
 * 存在的问题:
 * 1) 通常来说,传输的字段是可变长的,不是固定的,不应该固定buffer的容量或者检查固定的长度
 * 2) ChannelPipeline可以接收多个handler, 因此可以拆分多个模块来降低handler的复杂度
 */
public class TimeClientHandler1 extends ChannelInboundHandlerAdapter {
    private ByteBuf buf;

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) {
        buf = ctx.alloc().buffer(4); // (1)
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) {
        buf.release(); // (1)
        buf = null;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf m = (ByteBuf) msg;
        buf.writeBytes(m); // (2)
        m.release();

        if (buf.readableBytes() >= 4) { // (3)
            long currentTimeMillis = (buf.readUnsignedInt() - 2208988800L) * 1000L;
            System.out.println(Instant.ofEpochMilli(currentTimeMillis).atZone(ZoneId.systemDefault()));
            ctx.close();
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}
